﻿using System;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Win32.SafeHandles;

namespace Rsdn.Janus.Framework
{
    public static class SharedEvents
    {
        [Flags]
        private enum EventPermissions : uint
        {
            MUTEX_MODIFY_STATE =     0x000001,
            TIMER_QUERY_STATE =      0x000001,
            EVENT_MODIFY_STATE =     0x000002, //Modify state access, which is required for the SetEvent, ResetEvent and PulseEvent functions.
            SEMAPHORE_MODIFY_STATE = 0x000002,
            TIMER_MODIFY_STATE =     0x000002,
            DELETE =      (uint)     0x010000,
            READ_CONTROL=            0x020000,
            WRITE_DAC =(uint)        0x040000,
            WRITE_OWNER =            0x080000,
            MUTEX_ALL_ACCESS =       0x1F0001,
            SYNCHRONIZE =            0x100000,
            EVENT_ALL_ACCESS =       0x1F0003,
            SEMAPHORE_ALL_ACCESS =   0x1F0003,
            TIMER_ALL_ACCESS =       0x1F0003,
        }
        //OPEN EVENT
        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr OpenEvent(UInt32 dwDesiredAccess, Boolean bInheritHandle, String lpName);

        [DllImport("kernel32.dll")]
        private static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string lpName);

        public static IntPtr CreateEvent(string name)
        {
            IntPtr hEvent = IntPtr.Zero;
            hEvent = CreateEvent(IntPtr.Zero, true, false, "Global\\" + SharedConstants.JanusStartedEvent); //MLHIDE
            return hEvent;
        }

        /// <summary>
        /// Opens the event. 
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public static IntPtr OpenEvent(string name)
        {
            // Same as EVENT_ALL_ACCESS value
            UInt32 unEventPermissions = (uint) EventPermissions.EVENT_ALL_ACCESS; //2031619;

            // in the Win32 realm IntPtr hEvent = IntPtr.Zero; 
            // Get a handle to the Win32 Event.

            // The name, "MfcEventSource", is known in advance 
            IntPtr hEvent = IntPtr.Zero;

            hEvent = OpenEvent(unEventPermissions, true, "Global\\" + SharedConstants.JanusStartedEvent); //MLHIDE
            return hEvent;
        }

        /// <summary>
        /// Creates the slave event.
        /// </summary>
        /// <param name="systemEvent">The system event.</param>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public static AutoResetEvent CreateSlaveEvent(IntPtr systemEvent)
        {
            AutoResetEvent arEvent = new AutoResetEvent(false);

            // Set the Handle property to the external event HANDLE 
            SafeWaitHandle safeHandle = new SafeWaitHandle(systemEvent, false);

            //arEvent.Handle = hEvent;
            arEvent.SafeWaitHandle = safeHandle;
            return arEvent;
        }

        public static ManualResetEvent CreateMasterEvent(IntPtr systemEvent)
        {
            ManualResetEvent arEvent = new ManualResetEvent(false);

            // Set the Handle property to the external event HANDLE 
            SafeWaitHandle safeHandle = new SafeWaitHandle(systemEvent, true);

            //arEvent.Handle = hEvent;
            arEvent.SafeWaitHandle = safeHandle;
            return arEvent;
        }
    }
}
